package com.yuneec.fly.views;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;

import com.yuneec.fly.R;

/**
 * Created by zd.zhang on 2016/6/16.
 */
public class RadarProgressView extends ImageView {
    private float startAngle;
    private float range;
    private int max;
    private int opMax;// 负方向max
    private float pAngle;// 双向时 正方向角度
    private float nAngle; // 双向时 负方向角度
    private float p;// 当前角度
    private Paint paint = new Paint();
    private boolean clockwise;// 顺时针
    private float middleAngle;
    private int bgColor;
    private int progressColor;
    private float r;
    private int progressLineColor;
    private int progressTextColor;
    private int progressTextSize;
    private int progressTextBg;
    private float centerX;
    private float centerY;
    private RectF rf = null;
    private int mode;
    private int LINE_DV;
    private static final int Mode_Single = 0;
    private static final int Mode_TwoWay = 1;
    private static final int Mode_TwoWay4Circle = 2;
    Paint.FontMetrics ffm;
    private float angleOffset;

    public RadarProgressView(Context context) {
        super(context);
    }

    public RadarProgressView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initProp(context, attrs);
    }

    public RadarProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initProp(context, attrs);
    }

    private void initProp(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RadarProgressOption);
        startAngle = a.getFloat(R.styleable.RadarProgressOption_startAngle, 0);
        if (startAngle < 0) {
            int i = (int) (-startAngle / 360) + 1;
            startAngle += i * 360;
        }
        if (startAngle >= 360) {
            int i = (int) (startAngle / 360);
            startAngle -= i * 360;
        }
        range = a.getFloat(R.styleable.RadarProgressOption_rangle, 45);
        Math.min(range, 360);
        max = a.getInt(R.styleable.RadarProgressOption_max, 100);
        opMax = -a.getInt(R.styleable.RadarProgressOption_opMax, 100);
        p = a.getInt(R.styleable.RadarProgressOption_p, 0);
        clockwise = a.getBoolean(R.styleable.RadarProgressOption_clockWise, true);
        middleAngle = a.getFloat(R.styleable.RadarProgressOption_middleAngle, -1);
        bgColor = a.getColor(R.styleable.RadarProgressOption_shapColor, Color.parseColor("#656D72"));
        progressColor = a.getColor(R.styleable.RadarProgressOption_progressColor, Color.parseColor("#2280B3FF"));
        centerX = a.getDimension(R.styleable.RadarProgressOption_centerX, 0);
        progressLineColor = a.getColor(R.styleable.RadarProgressOption_progressLineColor, -1);
        centerY = a.getDimension(R.styleable.RadarProgressOption_centerY, 0);
        r = a.getDimension(R.styleable.RadarProgressOption_r, 0);
        progressTextColor = a.getColor(R.styleable.RadarProgressOption_progressTextColor, Color.BLACK);
        progressTextBg = a.getColor(R.styleable.RadarProgressOption_progressTextBg, Color.WHITE);
        progressTextSize = a.getDimensionPixelSize(R.styleable.RadarProgressOption_progressTextSize, 12);
        LINE_DV = a.getDimensionPixelOffset(R.styleable.RadarProgressOption_lineDv, 2);
        a.recycle();
        paint.setTextSize(progressTextSize);
        ffm = paint.getFontMetrics();

        rf = new RectF();
        rf.left = centerX - r;
        rf.right = centerX + r;
        rf.top = centerY - r;
        rf.bottom = centerY + r;
        if (middleAngle > startAngle && middleAngle < startAngle + range) {
            mode = Mode_TwoWay;
            if (clockwise) {
                nAngle = middleAngle - startAngle;
                pAngle = range - nAngle;
            } else {
                pAngle = middleAngle - startAngle;
                nAngle = range - pAngle;
            }
        } else if (startAngle == 0 && range == 360 && middleAngle >= 0 && middleAngle <= 360) {
            mode = Mode_TwoWay4Circle;
            pAngle = 180;
            nAngle = 180;
        } else {
            mode = Mode_Single;
        }
        if (startAngle + range > 360) {
            angleOffset = range;
        } else {
            angleOffset = 0;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(bgColor);
        canvas.drawArc(rf, startAngle, range, true, paint);
        float startAngle = this.startAngle;
        float sweepAngle = 0;
        double radians = 0;
        switch (mode) {
            case Mode_Single:
                sweepAngle = p * range / max;
                if (!clockwise) {
                    startAngle += range - sweepAngle;
                    radians = Math.toRadians(startAngle);
                } else {
                    radians = Math.toRadians(startAngle + sweepAngle);
                }
                break;
            case Mode_TwoWay:
                startAngle = middleAngle;
                if (clockwise) {
                    if (p > 0) {
                        sweepAngle = p * pAngle / max;
                        radians = Math.toRadians(startAngle + sweepAngle);
                    } else {
                        sweepAngle = p * nAngle / opMax;
                        startAngle -= sweepAngle;
                        radians = Math.toRadians(startAngle);
                    }
                } else {
                    if (p > 0) {
                        sweepAngle = p * pAngle / max;
                        startAngle -= sweepAngle;
                        radians = Math.toRadians(startAngle);
                    } else {
                        sweepAngle = p * nAngle / opMax;
                        radians = Math.toRadians(startAngle + sweepAngle);
                    }
                }
                break;
            case Mode_TwoWay4Circle:
                if (clockwise) {
                    if (p > 0) {
                        sweepAngle = p * pAngle / max;
                        radians = Math.toRadians(startAngle + sweepAngle);
                    } else {
                        sweepAngle = p * nAngle / opMax;
                        startAngle = 360 - sweepAngle;
                        radians = Math.toRadians(startAngle);
                    }
                } else {
                    if (p > 0) {
                        sweepAngle = p * pAngle / max;
                        startAngle = 360 - sweepAngle;
                        radians = Math.toRadians(startAngle);
                    } else {
                        sweepAngle = p * nAngle / opMax;
                        radians = Math.toRadians(startAngle + sweepAngle);
                    }
                }
                break;
        }
        paint.setColor(progressColor);
        canvas.drawArc(rf, startAngle, sweepAngle, true, paint);
        //画辅助线和提示圆圈
//        if (middleAngle == -1) {
//            radians = Math.toRadians(clockwise ? startAngle + sweepAngle : startAngle);
//        } else {
//            radians = Math.toRadians(startAngle >= middleAngle ? startAngle + sweepAngle : startAngle);
//        }
//        double radians = Math.toRadians(startAngle >= middleAngle ? startAngle + sweepAngle : startAngle);
        float sx = (float) ((r - LINE_DV) * Math.cos(radians) + centerX);
        float sy = (float) ((r - LINE_DV) * Math.sin(radians) + centerY);
        if (progressLineColor != -1) {
            paint.setColor(progressLineColor);
            canvas.drawLine(centerX, centerY, sx, sy, paint);
        }
        //
        float _r = getWidth() - r;
        float __r = progressTextSize * 1.5f;
        _r = _r > __r ? __r : _r;
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(progressTextBg);
        canvas.drawCircle(sx, sy, _r, paint);
        //
        paint.setColor(progressTextColor);
        String txt = getProgressString();
        float w = paint.measureText(txt);
        canvas.drawText(txt, sx - w / 2f, sy - (ffm.bottom + ffm.top) / 2, paint);

    }

    private int type = Type_No_Touch;
    private static final int Type_No_Touch = -1;
    private static final int Type_Touch_Down = 0;
    private static final int Type_Touch_Move = 1;

    public String getProgressString() {
        if (changed != null) {
            return changed.onTextShow(this, p);
        }
        return Float.toString(p);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                type = Type_Touch_Down;
                return touch(event.getX(), event.getY());
            case MotionEvent.ACTION_MOVE:
                type = Type_Touch_Move;
                return touch(event.getX(), event.getY());
            case MotionEvent.ACTION_UP:
                type = Type_No_Touch;
                break;
        }
        return true;
    }

    private boolean touch(float x, float y) {
        float degress = 0;
        float b = y - centerY;
        float a = x - centerX;
        if (a > 0) {
            if (b == 0) {
                degress = 0;
            } else if (b > 0) {
                degress = (float) Math.toDegrees(Math.atan(b / a));
            } else {
                degress = (float) Math.toDegrees(Math.atan(b / a)) + 360;
            }
        } else {
            if (a == 0) {
                if (b == 0) {
                    return true;
                } else if (b > 0) {
                    degress = 270;
                } else {
                    degress = 90;
                }
            } else {
                degress = (float) Math.toDegrees(Math.atan(b / a)) + 180;
            }
        }
        if (degress < startAngle) {
            degress += angleOffset;
        }
        switch (mode) {
            case Mode_Single:
                float proportion = (degress - startAngle) / range;
                proportion = Math.min(proportion, 1);
                if (clockwise) {
                    setProgress(proportion * max);
                } else {
                    setProgress(max - proportion * max);
                }
                break;
            case Mode_TwoWay:
                degress -= middleAngle;
                if (clockwise) {
                    if (degress > 0) {
                        proportion = degress / pAngle;
                        proportion = Math.min(proportion, 1);
                        setProgress(proportion * max);
                    } else {
                        proportion = degress / nAngle;
                        proportion = Math.max(proportion, -1);
                        setProgress(-proportion * opMax);
                    }
                } else {
                    if (degress > 0) {
                        proportion = degress / nAngle;
                        proportion = Math.min(proportion, 1);
                        setProgress(proportion * opMax);
                    } else {
                        proportion = degress / pAngle;
                        proportion = Math.max(proportion, -1);
                        setProgress(-proportion * max);
                    }
                }
                break;
            case Mode_TwoWay4Circle:
                if (middleAngle == 0) {
                    if (clockwise) {
                        if (degress >= 0 && degress <= 180) {
                            setProgress(degress * max / 180);
                        } else {
                            setProgress((360 - degress) * opMax / 180);
                        }
                    } else {
                        if (degress >= 0 && degress <= 180) {
                            setProgress(degress * opMax / 180);
                        } else {
                            setProgress((360 - degress) * max / 180);
                        }
                    }
                }
                break;
        }
        return true;
    }

    public void setProgress(float progress) {
        if (changed != null) {
            changed.onChangeProgress(this, p, progress);
        }
        this.p = progress;
        postInvalidate();
    }

    public float getProgress() {
        return this.p;
    }

    private OnProgressChanged changed;

    public void setOnProgressChanged(OnProgressChanged changed) {
        this.changed = changed;
    }

    public interface OnProgressChanged {
        void onChangeProgress(RadarProgressView view, float oldVal, float newVal);

        String onTextShow(RadarProgressView view, float p);
    }
}